<!--
 * @Description: 
 * @Author: chenjiaxin
 * @Date: 2022-02-19 18:35:10
 * @LastEditTime: 2022-02-20 16:25:33
 * @FilePath: \super-unit\test\inndex2.html
-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>测试</title>
  </head>
  <body></body>

  <!-- <script src="../lib/utils/index.js"></script> -->
  <script>
    let optoString = Object.prototype.toString;

    /**
     * 判断是否 是Date类型数据
     * @param {object} val
     * @returns {Boolean}
     */
    const isDate = (val) => {
      return optoString.call(val) === "[object Date]";
    };

    /**
     *
     * @param {*} value
     * @returns
     */
    const createIterableValue = (value) => {
      let n;
      switch (value) {
        case "Array":
          n = [];
          break;
        case "Set":
          n = new Set();
          break;
        case "Map":
          n = new Map();
          break;
        case "WeakSet":
          n = new WeakSet();
          break;
        case "WeakMap":
          n = new WeakMap();
          break;
        default:
          break;
      }
      return n;
    };
    // console.log(cloneDeep);
    const cloneDeep = (origin, map = new WeakMap()) => {
      let temp = null; //存储新数据
      if (origin && typeof origin === "object") {
        //Object Array 以及通过new 构造函数都是 object
        //判断是否是 可迭代对象。注：object对象 不是可迭代对象
        let iteratorObj = origin[Symbol.iterator] && origin[Symbol.iterator]();
        if (iteratorObj) {
          // 是可迭代对象 Array  Set  Map
          let origin_types = optoString.call(iteratorObj).replace(/\[|]/g, "").split(" "); // "[object Array Iterator]"
          let valueType = origin_types[1];
          temp = createIterableValue(valueType);

          if (map.has(origin)) {
            return map.get(origin);
          }
          map.set(origin, temp);

          for (const iterator of origin) {
            if (valueType === "Set" || valueType === "Map" || valueType === "WeakSet" || valueType === "WeakMap") {
              temp.add(cloneDeep(iterator, map));
            } else {
              temp.push(cloneDeep(iterator, map));
            }
          }
        } else {
          //不是可迭代对象 这里有object。
          temp = {}; //如果是Proxy对象 把它转成了普通的object对象
          if (map.has(origin)) {
            return map.get(origin);
          }
          map.set(origin, temp);
          for (const key in origin) {
            temp[key] = cloneDeep(origin[key], map);
          }
          // 对Symbol的key进行特殊的处理  for in 是遍历不出Symbol的key的
          let symbolKeys = Object.getOwnPropertySymbols(origin);
          for (const skey of symbolKeys) {
            temp[skey] = cloneDeep(origin[skey], map);
          }
        }
      } else {
        // string undefined boolean number null symbol function  bigint
        temp = origin;
      }
      return temp;
    };
    let sy1 = Symbol("aa");
    let sy2 = Symbol("bb");
    let set = new Set([1, 2, 3]);
    let set2 = new Set([sy1, sy2]);
    let obj = {
      nu: null,
      undef: undefined,
      b: true,
      name: "cjx",
      age: 18,
      user: {
        address: "深圳"
      },
      friends: ["json", "java"],
      [sy1]: "aa",
      sy2: sy2,
      set: set,
      set2: set2
    };
    obj.info = obj;

    // let newObj = cloneDeepObj(obj);
    let newObj = cloneDeep(obj);

    newObj.name = "coder";
    newObj.user.address = "北京";

    console.log(obj);
    console.log(newObj);
  </script>
</html>
